﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;



namespace iDMS.Models
{
    public enum WorkflowPrerequisitesResult { Passed, Fail, NothingChanged, UserNotInRole, UploadNotDone };
    public class WorkflowWrapper
    {

        private IDMSRepository _db { get; set; }
        public DesignChange DesignChange
        {
            get
            {
                return _designChange;
            }
        }
        private DesignChange _designChange;
        private WorkflowStep _workflowStep;
        public WorkflowStep WorkflowStep
        {
            get
            {
                return _workflowStep;
            }
        }
        private System.Security.Principal.IPrincipal user;


        public WorkflowPrerequisitesResult CheckPrerequisites()
        {
            if (!user.IsInRole(_workflowStep.RequiredRole))
            {
                return WorkflowPrerequisitesResult.UserNotInRole;
            }
            switch (_workflowStep.WorkflowStepID)
            {
                case 5:
                    return ToApprovalCheckPrerequisites();
                default:
                    return WorkflowPrerequisitesResult.Passed;

            }
        }

        private WorkflowPrerequisitesResult ToApprovalCheckPrerequisites()
        {
            bool areSheetsChanged = _db.SheetsGetAll().Where(d => d.DesignChangeID == _designChange.DesignChangeID || d.InnaplicableChangeID == _designChange.DesignChangeID).Any();
            bool areDrawingsChanged = _db.DrawingGetAll().Where(d => d.DesignChangeID == _designChange.DesignChangeID || d.InnaplicableDesignChangeID == _designChange.DesignChangeID).Any();

            bool areUploadsDone = !_db.SheetsGetAll().Where(d => d.DesignChangeID == _designChange.DesignChangeID).Where(s => s.ResourceID == null).Any();
            if (areDrawingsChanged || areSheetsChanged)
            {
                if (!areUploadsDone)
                {
                    return WorkflowPrerequisitesResult.UploadNotDone;
                }
                return WorkflowPrerequisitesResult.Passed;
            }
            else
            {
                return WorkflowPrerequisitesResult.NothingChanged;
            }


        }

        private void ToApprovalDoStep()
        {
            //_db.SheetsGetAll().Where(d => d.DesignChangeID == _designChange.DesignChangeID).ToList().ForEach(s => s.LifeCycleStatusID = 2);
        }

        private void CancelDoStep()
        {
            List<Drawing> drawingsCreated = _db.DrawingGetAll().Where(d => d.DesignChangeID == _designChange.DesignChangeID).ToList();
            foreach (Drawing item in drawingsCreated)
            {
                _db.DrawingDelete(item);
            }

            List<Drawing> drawingsWithdrawned = _db.DrawingGetAll().Where(d => d.InnaplicableDesignChangeID == _designChange.DesignChangeID).ToList();
            foreach (Drawing item in drawingsWithdrawned)
            {
                item.InnaplicableDesignChangeID = null;
            }

            List<Sheet> sheetsCreated = _db.SheetsGetAll().Where(s => s.DesignChangeID == _designChange.DesignChangeID).ToList();
            foreach (Sheet item in sheetsCreated)
            {
                _db.SheetDelete(item);
            }

            List<Sheet> sheetsWithdrawned = _db.SheetsGetAll().Where(s => s.InnaplicableChangeID == _designChange.DesignChangeID).ToList();
            foreach (Sheet item in sheetsWithdrawned)
            {
                item.InnaplicableChangeID = null;
                item.UnderRevisionWithdrawal = null;
            }

        }

        private void ReleaseDoStep()
        {
            List<Sheet> sheets_innaplicable = _db.SheetsGetAll().Where(s => s.InnaplicableChangeID == _designChange.DesignChangeID).ToList();
            foreach (Sheet item in sheets_innaplicable)
            {
                if (item.UnderRevisionWithdrawal.HasValue)
                {
                    if (item.UnderRevisionWithdrawal.Value)
                    {
                        item.LifeCycleStatusID = 5;
                    }
                    else
                    {
                        item.LifeCycleStatusID = 6;
                    }
                }
                else
                {
                    throw new ArgumentException(item.Drawing.Identifier + ";" + item.PageNmb.ToString() + ";" + item.Revision + "- underRevisionWithdrawal");
                }
            }

            List<Drawing> drawings_innaplicable = _db.DrawingGetAll().Where(d => d.InnaplicableDesignChangeID == _designChange.DesignChangeID).ToList();
            foreach (Drawing item in drawings_innaplicable)
            {
                item.isWithdrawn = true;
            }
        }

        public void DoStep(Employee employee, String comment)
        {
            switch (_workflowStep.WorkflowStepID)
            {
                case 5:
                    ToApprovalDoStep();
                    break;
                case 6:
                    CancelDoStep();
                    break;
                case 10:
                    ReleaseDoStep();
                    break;
            }
            doCommonStepActions(employee, comment);
        }
        private void doCommonStepActions(Employee employee, String comment)
        {
            if (_workflowStep.CreatedSheetStatus.HasValue)
            {
                _db.SheetsGetAll().Where(d => d.DesignChangeID == _designChange.DesignChangeID).ToList().ForEach(s => s.LifeCycleStatusID = _workflowStep.CreatedSheetStatus.Value);
            }
            byte oldPhase = _designChange.PhaseID;
            _designChange.PhaseID = _workflowStep.PhaseTo;
            _designChange.LastModified = DateTime.Now;
            LogDCPhaseChange(employee.EmployeeID, oldPhase, _workflowStep.PhaseTo, comment);
        }

        public WorkflowWrapper(IDMSRepository repository, DesignChange designChange, byte newPhase, System.Security.Principal.IPrincipal user)
        {
            this._db = repository;
            WorkflowStep step = _db.WorkflowStepsGetAll().SingleOrDefault(d => d.PhaseFrom == designChange.PhaseID && d.PhaseTo == newPhase);
            if (step != null)
            {
                this._designChange = designChange;
                this._workflowStep = step;
                this.user = user;
            }
            else
            {
                throw new ArgumentException("Step not Found");
            }
        }

        public DesignChangeStepViewModel GetViewModel()
        {
            DesignChangeStepViewModel result = new DesignChangeStepViewModel();
            result.DesignChange = _designChange;
            result.WorkflowStep = _workflowStep;
            return result;
        }



        private void LogDCPhaseChange(int employeeID, byte oldPhase, byte newPhase, string comment)
        {
            DesignChangeLog log = new DesignChangeLog();
            log.DateTime = DateTime.Now;
            log.DesignChange = _designChange;
            log.EmployeeID = employeeID;
            log.PhaseIdNew = newPhase;
            log.PhaseIdOld = oldPhase;
            log.Comment = comment;
            _db.DesignChangeLogAdd(log);
        }
    }
}